// Copyright Gary Evans 2006.

using System;

namespace Taumuon.Jabuka.Physics
{
    /// <summary>
    /// A rigid body that updates its location
    ///  via Euler integration.
    /// </summary>
    public class EulerRigidBody
    {
        #region Member Variables

        private Vector location = null;
        private Vector velocity = null;
        private Vector force = null;
        private double mass = 0.0;

        #endregion Member Variables

        #region Object Lifetime

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="location">Initial location.</param>
        /// <param name="velocity">Initial velocity.</param>
        /// <param name="mass">The body's mass.</param>
        /// <exception cref="ArgumentException">
        /// if mass is zero
        /// </exception>
        /// <exception cref="ArgumentNullException"/>
        public EulerRigidBody(Vector location, Vector velocity, double mass)
        {
            if (mass == 0.0)
            {
                throw new ArgumentException("mass cannot be zero");
            }
            if (location == null)
            {
                throw new ArgumentNullException(
                    "location");
            }
            if (velocity == null)
            {
                throw new ArgumentNullException(
                    "velocity");
            }
            this.location = location;
            this.velocity = velocity;
            this.mass = mass;
            ScreenTranslate = new Vector(0, 0, 0);
        }

        #endregion Object Lifetime

        #region Public Accessors
        public Vector ScreenTranslate
        {
            get;set;
        }
        /// <summary>
        /// Retrieves the current location.
        /// </summary>
        public Vector Location
        {
            get
            {
                return this.location;
            }
        }

        public Vector ScreenCoordinate
        {
            get
            {
                return Location + ScreenTranslate;
            }
        }

        /// <summary>
        /// Retrieves the current velocity.
        /// </summary>
        public Vector Velocity
        {
            get
            {
                return this.velocity;
            }
        }

        #endregion Public Accessors

        #region Public Methods

        /// <summary>
        /// Allows the body to update its physical state.
        /// </summary>
        /// <param name="deltaTime">Time increment, in seconds.</param>
        public void Update(double deltaTime)
        {
            if (this.force == null)
            {
                this.force = new Vector(0.0, 0.0, 0.0);
            }
            Vector acceleration = this.force * (1.0 / mass);
            this.velocity += acceleration * deltaTime;
            this.location += this.velocity * deltaTime;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="z"></param>
        public void Update(int x, int y, int z)
        {
            ScreenTranslate = new Vector(x, y, z);
        }

     //   public 

        /// <summary>
        /// Applies a force to the body.
        /// </summary>
        /// <param name="force">Force, in Newtons.</param>
        public void ApplyForce(Vector force)
        {
            this.force = force;
        }

        #endregion Public Methods
    }
}
